package com.justindav1s.homecontrol;

import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.UUID;

public class BluetoothConnectionManager extends Thread {

    public BluetoothSocket mmSocket;
    private final BluetoothDevice mmDevice;
    private final BluetoothAdapter mBluetoothAdapter;
    private final Handler clientHandler;
    private final UUID uuid;

    public BluetoothConnectionManager(Handler _clientHandler,
                                      BluetoothAdapter _mBluetoothAdapter,
                                      BluetoothDevice _device,
                                      UUID _uuid) {

        Log.d(Constants.LOGTAG, "Creating BluetoothConnectionManager");
        uuid = _uuid;
        mmDevice = _device;
        mBluetoothAdapter = _mBluetoothAdapter;
        clientHandler = _clientHandler;
    }

    public void run() {

        Log.d(Constants.LOGTAG, "Connecting ...");
        // Cancel discovery because it will slow down the connection
        mBluetoothAdapter.cancelDiscovery();

        BluetoothSocket tmp = null;
        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            // MY_UUID is the app's UUID string, also used by the server code
            //tmp = mmDevice.createRfcommSocketToServiceRecord(uuid);
            //tmp = mmDevice.createInsecureRfcommSocketToServiceRecord(uuid);
            Method m = null;
            m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] { int.class });
            tmp = (BluetoothSocket) m.invoke(mmDevice, 1);



        } catch (NoSuchMethodException e) {
                e.printStackTrace();
        } catch (InvocationTargetException e) {
                e.printStackTrace();
        } catch (IllegalAccessException e) {
                e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
            this.sendDataMessage(Constants.DISCONNECTED_MSG_TYPE, e.getMessage());
        }
        mmSocket = tmp;

        Log.d(Constants.LOGTAG, "Socket : "+ mmSocket);

        try {
            // Connect the device through the socket. This will block
            // until it succeeds or throws an exception
            Log.d(Constants.LOGTAG, "Socket connected : " +mmSocket.isConnected());
            mmSocket.connect();
            Log.d(Constants.LOGTAG, "Socket connected !! : " +mmSocket.isConnected());
            Log.d(Constants.LOGTAG, Constants.CONNECTED_TO+mmDevice.getName());
        } catch (IOException e) {
            e.printStackTrace();
            this.sendDataMessage(Constants.DISCONNECTED_MSG_TYPE, e.getMessage());
            try {
                mmSocket.close();
            } catch (IOException closeException) {
                e.printStackTrace();
                this.sendDataMessage(Constants.DISCONNECTED_MSG_TYPE, e.getMessage());
            }
            return;
        }

        // Do work to manage the connection (in a separate thread)
        Message msg = new Message();
        msg.getData().putString(Constants.TYPE, Constants.CONNECTED_MSG_TYPE);
        clientHandler.sendMessage(msg);
    }

    /** Will cancel an in-progress connection, and close the socket */
    public void close() {
        try {
            Log.d(Constants.LOGTAG, "Closing Connection");
            if (mmSocket != null) mmSocket.close();
            Log.d(Constants.LOGTAG, "Connection Closed");
        } catch (IOException e) {
            e.printStackTrace();
            this.sendDataMessage(Constants.DISCONNECTED_MSG_TYPE, e.getMessage());
        }
    }

    private void sendDataMessage(String _type, String _data)  {
        Message msg = new Message();
        msg.getData().putString(Constants.TYPE, _type);
        msg.getData().putString(Constants.CONTENT, _data);
        clientHandler.sendMessage(msg);
    }
}